home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / net / sun3.md / netLE.c < prev    next >
C/C++ Source or Header  |  1991-08-02  |  14KB  |  542 lines

  1. /* 
  2.  * netLE.c --
  3.  *
  4.  *    The main routines for the device driver for the AMD 7990 Ethernet 
  5.  *    Controller.
  6.  *
  7.  *
  8.  * TODO: Watch dogs to make sure that the chip does not get stuck.  Rumor has
  9.  *     it that because of bugs in the chip it can get stuck at any time for
  10.  *     no particular reason.
  11.  *
  12.  * Copyright 1988 Regents of the University of Californiaf
  13.  * Permission to use, copy, modify, and distribute this
  14.  * software and its documentation for any purpose and without
  15.  * fee is hereby granted, provided that the above copyright
  16.  * notice appear in all copies.  The University of California
  17.  * makes no representations about the suitability of this
  18.  * software for any purpose.  It is provided "as is" without
  19.  * express or implied warranty.
  20.  *
  21.  */
  22.  
  23. #ifndef lint
  24. static char rcsid[] = "$Header: /sprite/src/kernel/net/sun3.md/RCS/netLE.c,v 9.13 91/08/02 17:43:23 jhh Exp $ SPRITE (Berkeley)";
  25. #endif not lint
  26.  
  27. #include <sprite.h>
  28. #include <sys.h>
  29. #include <list.h>
  30. #include <netInt.h>
  31. #include <netLEInt.h>
  32. #include <vm.h>
  33. #include <vmMach.h>
  34. #include <mach.h>
  35. #include <machMon.h>
  36. #include <dbg.h>
  37. #include <assert.h>
  38. #ifdef sun4c
  39. #include <devSCSIC90.h>
  40. #endif
  41.  
  42.  
  43. /*
  44.  *----------------------------------------------------------------------
  45.  *
  46.  * NetLEInit --
  47.  *
  48.  *    Initialize the LANCE AMD 7990 Ethernet chip.
  49.  *
  50.  * Results:
  51.  *    SUCCESS if the LANCE controller was found and initialized,
  52.  *    FAILURE otherwise.
  53.  *
  54.  * Side effects:
  55.  *    Initializes the netEtherFuncs record, as well as the chip.
  56.  *
  57.  *----------------------------------------------------------------------
  58.  */
  59.  
  60. ReturnStatus
  61. NetLEInit(interPtr)
  62.     Net_Interface    *interPtr;     /* Network interface. */
  63. {
  64.     int         i;
  65.     List_Links        *itemPtr;
  66.     NetLEState        *statePtr;
  67.     ReturnStatus    status;
  68.     void        NetLETrace();
  69.  
  70.     assert(sizeof(NetLE_Reg) == NET_LE_REG_SIZE);
  71.     assert(sizeof(NetLEModeReg) == 2);
  72.     assert(sizeof(NetLERingPointer) == 4);
  73.     assert(sizeof(NetLEInitBlock) == 24);
  74.     assert(sizeof(NetLERecvMsgDesc) == 8);
  75.     assert(sizeof(NetLEXmitMsgDesc) == 8);
  76.  
  77.     statePtr = (NetLEState *) malloc (sizeof(NetLEState));
  78.     bzero((char *) statePtr, sizeof(NetLEState));
  79.     MASTER_LOCK(&interPtr->mutex)
  80.     statePtr->running = FALSE;
  81.     status = NetLEMachInit(interPtr, statePtr);
  82.     if (status != SUCCESS) {
  83.     MASTER_UNLOCK(&interPtr->mutex);
  84.     free((char *) statePtr);
  85.     return status;
  86.     }
  87.  
  88.     /*
  89.      * Initialize the transmission list.  
  90.      */
  91.  
  92.     statePtr->xmitList = &statePtr->xmitListHdr;
  93.     List_Init(statePtr->xmitList);
  94.  
  95.     statePtr->xmitFreeList = &statePtr->xmitFreeListHdr;
  96.     List_Init(statePtr->xmitFreeList);
  97.  
  98.     for (i = 0; i < NET_LE_NUM_XMIT_ELEMENTS; i++) {
  99.     itemPtr = (List_Links *) malloc(sizeof(NetXmitElement)), 
  100.     List_InitElement(itemPtr);
  101.     List_Insert(itemPtr, LIST_ATREAR(statePtr->xmitFreeList));
  102.     }
  103.  
  104.     /*
  105.      * Allocate the initialization block.
  106.      */
  107.     statePtr->initBlockPtr = 
  108.         (NetLEInitBlock *) BufAlloc(statePtr, sizeof(NetLEInitBlock));
  109.     interPtr->init    = NetLEInit;
  110.     interPtr->output     = NetLEOutput;
  111.     interPtr->intr    = NetLEIntr;
  112.     interPtr->reset     = NetLERestart;
  113.     interPtr->getStats    = NetLEGetStats;
  114.     interPtr->netType    = NET_NETWORK_ETHER;
  115.     interPtr->maxBytes    = NET_ETHER_MAX_BYTES - sizeof(Net_EtherHdr);
  116.     interPtr->minBytes    = 0;
  117.     interPtr->interfaceData = (ClientData) statePtr;
  118.     NET_ETHER_ADDR_COPY(statePtr->etherAddress, 
  119.     interPtr->netAddress[NET_PROTO_RAW].ether);
  120.     interPtr->broadcastAddress.ether = netEtherBroadcastAddress.ether;
  121.     interPtr->flags |= NET_IFLAGS_BROADCAST;
  122.     statePtr->interPtr = interPtr;
  123.     statePtr->recvMemInitialized = FALSE;
  124.     statePtr->recvMemAllocated = FALSE;
  125.     statePtr->xmitMemInitialized = FALSE;
  126.     statePtr->xmitMemAllocated = FALSE;
  127.     statePtr->resetPending = FALSE;
  128.  
  129.     /*
  130.      * Reset the world.
  131.      */
  132.  
  133.     NetLEReset(interPtr);
  134.  
  135.     /*
  136.      * Now we are running.
  137.      */
  138.  
  139.     statePtr->running = TRUE;
  140.     MASTER_UNLOCK(&interPtr->mutex);
  141.     return (SUCCESS);
  142. }
  143.  
  144.  
  145. /*
  146.  *----------------------------------------------------------------------
  147.  *
  148.  * NetLEReset --
  149.  *
  150.  *    Reset the interface.
  151.  *
  152.  * Results:
  153.  *    None.
  154.  *
  155.  * Side effects:
  156.  *    All of the pointers in the interface structure are initialized.
  157.  *
  158.  *----------------------------------------------------------------------
  159.  */
  160.  
  161. void
  162. NetLEReset(interPtr)
  163.     Net_Interface    *interPtr; /* Interface to reset. */
  164. {
  165.     volatile NetLEInitBlock *initPtr;
  166.     NetLEState            *statePtr;
  167.     int                i;
  168.     int                j;
  169.     unsigned short        csr0;
  170.  
  171.     statePtr = (NetLEState *) interPtr->interfaceData;
  172.     /*
  173.      * If there isn't a reset pending already, and the chip is currently
  174.      * transmitting then just set the pending flag.  With any luck
  175.      * this mechanism will prevent the chip from being reset right in
  176.      * the middle of a packet.
  177.      */
  178.     if (!(statePtr->resetPending) && (statePtr->transmitting)) {
  179.     printf("Deferring reset.\n");
  180.     statePtr->resetPending = TRUE;
  181.     return;
  182.     }
  183.     statePtr->resetPending = FALSE;
  184.     /* 
  185.      * Reset (and stop) the chip.
  186.      */
  187.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR0_ADDR);
  188.     Mach_EmptyWriteBuffer();
  189.     statePtr->regPortPtr->dataPort = NET_LE_CSR0_STOP;
  190.     interPtr->flags &= ~NET_IFLAGS_RUNNING;
  191. #ifdef sun4c
  192.     Dev_ScsiResetDMA();
  193. #endif
  194.  
  195.     /*
  196.      * Set up the receive and transmit rings. 
  197.      */
  198.      NetLERecvInit(statePtr);
  199.      NetLEXmitInit(statePtr);
  200.  
  201.     /*
  202.      *  Fill in the initialization block. Make everything zero unless 
  203.      *  told otherwise.
  204.      */
  205.  
  206.     bzero( (Address) statePtr->initBlockPtr, sizeof(NetLEInitBlock));
  207.     initPtr = statePtr->initBlockPtr;
  208.  
  209.     /*
  210.      * Insert the ethernet address.
  211.      */
  212.  
  213. #ifndef ds5000
  214.     {
  215.     Net_EtherAddress    revAddr;
  216.     revAddr.byte2 = statePtr->etherAddress.byte1;
  217.     revAddr.byte1 = statePtr->etherAddress.byte2;
  218.     revAddr.byte4 = statePtr->etherAddress.byte3;
  219.     revAddr.byte3 = statePtr->etherAddress.byte4;
  220.     revAddr.byte6 = statePtr->etherAddress.byte5;
  221.     revAddr.byte5 = statePtr->etherAddress.byte6;
  222.     bcopy((char *) &revAddr, (char *) &initPtr->etherAddress, 
  223.     sizeof(statePtr->etherAddress));
  224.     }
  225. #else
  226.     bcopy((char *) &statePtr->etherAddress, (char *) &initPtr->etherAddress, 
  227.     sizeof(statePtr->etherAddress));
  228. #endif
  229.  
  230.     /*
  231.      * Reject all multicast addresses, except for those generated by bootp.
  232.      * These are address ab-00-00-01-00-00 = hash bit 31, maybe?
  233.      */
  234.  
  235.     initPtr->multiCastFilter[0] = 0x8000; /* Bit 31 apparently. */
  236.     initPtr->multiCastFilter[1] = 0;
  237.     initPtr->multiCastFilter[2] = 0;
  238.     initPtr->multiCastFilter[3] = 0;
  239.  
  240.     /*
  241.      * Set up the ring pointers.
  242.      */
  243.  
  244.     NetBfShortSet(initPtr->recvRing, LogRingLength, 
  245.         NET_LE_NUM_RECV_BUFFERS_LOG2);
  246.     NetBfShortSet(initPtr->recvRing, RingAddrLow, 
  247.         NET_LE_TO_CHIP_ADDR_LOW(statePtr->recvDescFirstPtr));
  248.     NetBfShortSet(initPtr->recvRing, RingAddrHigh, 
  249.         NET_LE_TO_CHIP_ADDR_HIGH(statePtr->recvDescFirstPtr));
  250.  
  251.     NetBfShortSet(initPtr->xmitRing, LogRingLength, 
  252.         NET_LE_NUM_XMIT_BUFFERS_LOG2);
  253.     NetBfShortSet(initPtr->xmitRing, RingAddrLow, 
  254.         NET_LE_TO_CHIP_ADDR_LOW(statePtr->xmitDescFirstPtr));
  255.     NetBfShortSet(initPtr->xmitRing, RingAddrHigh, 
  256.         NET_LE_TO_CHIP_ADDR_HIGH(statePtr->xmitDescFirstPtr));
  257.  
  258.     /*
  259.      * Set the the Bus master control register (csr3) to have chip byte
  260.      * swap for us. he sparcStation appears to need active low and
  261.      * byte control on.
  262.      */
  263.  
  264.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR3_ADDR);
  265.     Mach_EmptyWriteBuffer();
  266.     statePtr->regPortPtr->dataPort = 0;
  267.     Mach_EmptyWriteBuffer();
  268.     statePtr->regPortPtr->dataPort = NET_LE_CSR3_VALUE;
  269.  
  270.     /*
  271.      * Set the init block pointer address in csr1 and csr2
  272.      */
  273.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR1_ADDR);
  274.     Mach_EmptyWriteBuffer();
  275.     NetBfShortSet(&statePtr->regPortPtr->dataPort, DataCSR1, 
  276.         NET_LE_TO_CHIP_ADDR_LOW(initPtr));
  277.     Mach_EmptyWriteBuffer();
  278.  
  279.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR2_ADDR);
  280.     Mach_EmptyWriteBuffer();
  281.     NetBfShortSet(&statePtr->regPortPtr->dataPort, DataCSR2, 
  282.         NET_LE_TO_CHIP_ADDR_HIGH(initPtr));
  283.     Mach_EmptyWriteBuffer();
  284.  
  285.     /*
  286.      * Tell the chip to initialize and wait for results.
  287.      */
  288.     csr0 = 0;
  289.     for (j = 0; (j < 100) && ((csr0 & NET_LE_CSR0_INIT_DONE) == 0); j++) {
  290.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, 
  291.         NET_LE_CSR0_ADDR);
  292.     Mach_EmptyWriteBuffer();
  293.     statePtr->regPortPtr->dataPort = NET_LE_CSR0_INIT;
  294.     Mach_EmptyWriteBuffer();
  295.  
  296.  
  297.     for (i = 0; i < 10000; i++) {
  298.         csr0 = statePtr->regPortPtr->dataPort;
  299.         if (csr0 & NET_LE_CSR0_INIT_DONE) {
  300.         break;
  301.         }
  302.     }
  303.     if (csr0 & NET_LE_CSR0_INIT_DONE) {
  304.         break;
  305.     }
  306.     }
  307.     if (!(csr0 & NET_LE_CSR0_INIT_DONE)) {
  308.     panic("LE ethernet: Chip will not initialize, csr0 = 0x%x\n", csr0);
  309.     }
  310.     MACH_DELAY(100);
  311.  
  312.     /*
  313.      * Ack the interrupt.
  314.      */
  315.     statePtr->regPortPtr->dataPort = NET_LE_CSR0_INIT_DONE;
  316.  
  317.     /*
  318.      * Start the chip and enable interrupts.
  319.      */
  320.     statePtr->regPortPtr->dataPort = 
  321.     (NET_LE_CSR0_START | NET_LE_CSR0_INTR_ENABLE);
  322.  
  323.     printf("LE ethernet: Reinitialized chip.\n");
  324.     statePtr->numResets++;
  325.     interPtr->flags |= NET_IFLAGS_RUNNING;
  326.     return;
  327. }
  328.  
  329.  
  330. /*
  331.  *----------------------------------------------------------------------
  332.  *
  333.  * NetLERestart --
  334.  *
  335.  *    Reinitialize the LANCE Ethernet chip.
  336.  *
  337.  * Results:
  338.  *    None.
  339.  *
  340.  * Side effects:
  341.  *    None.
  342.  *
  343.  *----------------------------------------------------------------------
  344.  */
  345. void
  346. NetLERestart(interPtr)
  347.     Net_Interface    *interPtr;     /* Interface to restart. */
  348. {
  349.  
  350.     NetLEState    *statePtr = (NetLEState *) interPtr->interfaceData;
  351.  
  352.     MASTER_LOCK(&interPtr->mutex);
  353.  
  354.     /*
  355.      * Drop the current packet so the sender does't get hung.
  356.      */
  357.     NetLEXmitDrop(statePtr);
  358.  
  359.     /*
  360.      * Reset the world.
  361.      */
  362.     NetLEReset(interPtr);
  363.  
  364.     /*
  365.      * Restart transmission of packets.
  366.      */
  367.     NetLEXmitRestart(statePtr);
  368.  
  369.     MASTER_UNLOCK(&interPtr->mutex);
  370.     return;
  371. }
  372.  
  373.  
  374. /*
  375.  *----------------------------------------------------------------------
  376.  *
  377.  * NetLEIntr --
  378.  *
  379.  *    Process an interrupt from the LANCE chip.
  380.  *
  381.  * Results:
  382.  *    None.
  383.  *
  384.  * Side effects:
  385.  *    None.
  386.  *
  387.  *----------------------------------------------------------------------
  388.  */
  389. void
  390. NetLEIntr(interPtr, polling)
  391.     Net_Interface    *interPtr;    /* Interface to process. */
  392.     Boolean        polling;    /* TRUE if are being polled instead of
  393.                      * processing an interrupt. */
  394. {
  395.     register    NetLEState    *statePtr;
  396.     ReturnStatus        statusXmit, statusRecv;
  397.     unsigned     short        csr0;
  398.     Boolean            reset;
  399.  
  400.     statePtr = (NetLEState *) interPtr->interfaceData;
  401.  
  402.     NetBfShortSet(statePtr->regPortPtr->addrPort, AddrPort, NET_LE_CSR0_ADDR);
  403.     Mach_EmptyWriteBuffer();
  404.     csr0 = statePtr->regPortPtr->dataPort;
  405.     if (netDebug) {
  406.     printf("NetLEIntr: %s, csr0 = 0x%x\n", (polling == TRUE) ? "polling" : 
  407.         "not polling", csr0);
  408.     }
  409.     if (csr0 & NET_LE_CSR0_STOP) {
  410.     printf("NetLEIntr: chip is stopped.\n");
  411.     NetLERestart(interPtr);
  412.     return;
  413.     }
  414.  
  415.     csr0 &= ~NET_LE_CSR0_INTR_ENABLE;
  416.     statePtr->regPortPtr->dataPort = csr0;
  417.     statePtr->regPortPtr->dataPort = NET_LE_CSR0_INTR_ENABLE;
  418.     if ( !((csr0 & NET_LE_CSR0_ERROR) || (csr0 & NET_LE_CSR0_INTR)) ) {
  419.     /*
  420.      * We could be polling; that's why we were here.
  421.      */
  422.     if (!polling) {
  423.         printf("LE ethernet: Spurious interrupt CSR0 = <%x>\n", csr0);
  424.         NetLERestart(interPtr);
  425.     } 
  426.     return;
  427.     } 
  428.  
  429.     /*
  430.      * Check for errors.
  431.      */
  432.  
  433.     if (csr0 & NET_LE_CSR0_ERROR) {
  434.     reset = TRUE;
  435.     if (csr0 & NET_LE_CSR0_MISSED_PACKET) {
  436.         printf("LE ethernet: Missed a packet.\n");
  437.         /*
  438.          * Don't reset controller.
  439.          */
  440.         reset = FALSE;
  441.     }
  442.     if (csr0 & NET_LE_CSR0_COLLISION_ERROR) {
  443.         /*
  444.          * Late collision error appear to happen when the machine
  445.          * is disconnected from the transceiver. When this happens
  446.          * we will complain about Lost of Carrier so the late
  447.          * collision message is uncessary.
  448.          *
  449.          * printf("LE ethernet: Late collision.\n");
  450.          */
  451.         reset = FALSE;
  452.     }
  453.     /*
  454.      * Check for fatal errors.  Kill the machine if we start babbling 
  455.      * (sending oversize ethernet packets). 
  456.      */
  457.     if (csr0 & NET_LE_CSR0_BABBLE) {
  458.         NetLEReset(interPtr);
  459.         panic("LE ethernet: Transmit babble\n");
  460.     }
  461.     if (csr0 & NET_LE_CSR0_MEMORY_ERROR) {
  462.         printf(
  463.     "statePtr: 0x%x, regPortPtr = 0x%x, dataPort = 0x%x, csr0: 0x%x\n", 
  464.         statePtr, statePtr->regPortPtr, statePtr->regPortPtr->dataPort, 
  465.         csr0);
  466.         panic("LE ethernet: Memory Error.\n");
  467.     }
  468.     /*
  469.      * Clear the error the easy way, reinitialize everything.
  470.      */
  471.     if (reset == TRUE) {
  472.         NetLERestart(interPtr);
  473.         return;
  474.     }
  475.     }
  476.  
  477.     statusRecv = statusXmit = SUCCESS;
  478.     /*
  479.      * Did we receive a packet.
  480.      */
  481.     if (csr0 & NET_LE_CSR0_RECV_INTR) {
  482.     statusRecv = NetLERecvProcess(FALSE, statePtr);
  483.     }
  484.     /*
  485.      * Did we transmit a packet.
  486.      */
  487.     if (csr0 & NET_LE_CSR0_XMIT_INTR) {
  488.     statusXmit = NetLEXmitDone(statePtr);
  489.     }
  490.     /*
  491.      * Did the chip magically initialize itself?
  492.      */
  493.     if (csr0 & NET_LE_CSR0_INIT_DONE) {
  494.     printf( "LE ethernet: Chip initialized itself!!\n");
  495.     /*
  496.      * Better initialize it the way we want it.
  497.      */
  498.     statusRecv = FAILURE;
  499.     }
  500.  
  501.     if (statusRecv != SUCCESS || statusXmit != SUCCESS) {
  502.     NetLERestart(interPtr);
  503.     return;
  504.     }
  505.     /*
  506.      * If interrupts aren't enabled or there is no interrupt pending, then
  507.      * what are we doing here?
  508.      */
  509.  
  510.     return;
  511. }
  512.  
  513. /*
  514.  *----------------------------------------------------------------------
  515.  *
  516.  * NetLEGetStats --
  517.  *
  518.  *    Return the statistics for the interface.
  519.  *
  520.  * Results:
  521.  *    A pointer to the statistics structure.
  522.  *
  523.  * Side effects:
  524.  *    None.
  525.  *
  526.  *----------------------------------------------------------------------
  527.  */
  528.  
  529. ReturnStatus
  530. NetLEGetStats(interPtr, statPtr)
  531.     Net_Interface    *interPtr;        /* Current interface. */
  532.     Net_Stats        *statPtr;        /* Statistics to return. */
  533. {
  534.     NetLEState    *statePtr;
  535.     statePtr = (NetLEState *) interPtr->interfaceData;
  536.     MASTER_LOCK(&interPtr->mutex);
  537.     statPtr->ether = statePtr->stats;
  538.     MASTER_UNLOCK(&interPtr->mutex);
  539.     return SUCCESS;
  540. }
  541.  
  542.